class MigrateSecuritySetup < ActiveRecord::Migration

  class << self
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Database create/drop methods
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def up
      create_roles_table
      create_users_table
      create_user_groups_table
      create_user_address_types_table
      create_user_addresses_table
      create_user_contact_types_table
      create_user_contacts_table
      create_system_objects_table
      create_system_methods_table
    end

    def down
      drop_system_methods_table
      drop_system_objects_table
      drop_user_contacts_table
      drop_user_contact_types_table
      drop_user_addresses_table
      drop_user_address_types_table
      drop_user_groups_table
      drop_users_table
      drop_roles_table
    end

    private
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      # Table create/drop methods
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
      def create_roles_table
        create_table_with_privies(:roles, :force => true) do |t|
          t.column("name", :string, :limit => 40, :null => false)
          t.column("gather_contact_info", :boolean, :default => false)
          t.column("gather_address_info", :boolean, :default => false)
        end
      end

      def drop_roles_table
        execute("select setval('roles_id_seq',1,false)")
        drop_table(:roles)
      end

      def create_users_table
        create_table_with_history(:users, :force => true) do |t|
          t.column("first_name", :text, :null => false)
          t.column("middle_name", :text)
          t.column("last_name", :text, :null => false)
          t.column("login", :text, :null => false)
          t.column("password", :text)
          t.column("reset_password", :boolean, :default => false)
          t.column("role_id", :integer)
          t.column("updater_id", :integer, :null => false)
          t.column("updated_by", :integer, :null => false)
          t.column("updated_at", :datetime)
        end

        add_index "users", ["login"], :name => "users_login_key", :unique => true

        foreign_key(:users, :role_id, :roles)
        foreign_key(:users, :updater_id, :updaters)
        foreign_key(:users, :updated_by, :updaters)
      end

      def drop_users_table
        execute("select setval('users_id_seq',1,false)")
        drop_table_with_history(:users)
      end

      def create_user_groups_table
        create_table_with_privies(:user_groups, :force => true) do |t|
          t.column("name", :text)
          t.column("role_id", :integer, :null => false)
        end

        create_lookup_table(:user_groups,:users)

        foreign_key(:user_groups, :role_id, :roles)
      end

      def drop_user_groups_table
        drop_lookup_table(:user_groups,:users)
        drop_table(:user_groups)
      end


      def create_user_address_types_table
        create_table_with_privies(:user_address_types, :force => true) do |t|
          t.column("name", :string, :limit => 20, :null => false)
          t.column("is_active", :boolean, :default => true)
          t.column("is_required", :boolean, :default => false)
        end

        UserAddressType.create(:name => "Work", :is_required => true)
      end

      def drop_user_address_types_table
        execute("select setval('user_address_types_id_seq',1,false)")
        drop_table(:user_address_types)
      end

      def create_user_addresses_table
        create_table_with_history(:user_addresses, :force => true) do |t|
          t.column("user_id", :integer)
          t.column("user_address_type_id", :integer)
          t.column("address_id", :integer)
          t.column("updated_by", :integer, :null => false)
          t.column("updated_at", :datetime)
        end

        foreign_key(:user_addresses, :user_id, :users)
        foreign_key(:user_addresses, :user_address_type_id, :user_address_types)
        foreign_key(:user_addresses, :address_id, :addresses)
        foreign_key(:user_addresses, :updated_by, :updaters)
      end

      def drop_user_addresses_table
        drop_table_with_history(:user_addresses)
      end

      def create_user_contact_types_table
        create_table_with_privies(:user_contact_types, :force => true) do |t|
          t.column("name", :string, :limit => 40, :null => false)
          t.column("contact_format_id", :integer)
          t.column("is_active", :boolean, :default => true)
          t.column("is_required", :boolean, :default => false)
        end

        foreign_key(:user_contact_types, :contact_format_id, :contact_formats)

        UserContactType.create(:name => "Email", :contact_format_id => 2, :is_required => true)
        UserContactType.create(:name => "Work Phone", :contact_format_id => 1, :is_required => true)
      end

      def drop_user_contact_types_table
        execute("select setval('user_contact_types_id_seq',1,false)")
        drop_table(:user_contact_types)
      end

      def create_user_contacts_table
        create_table_with_history(:user_contacts, :force => true) do |t|
          t.column("user_id", :integer, :null => false)
          t.column("user_contact_type_id", :integer)
          t.column("value", :text, :null => false)
          t.column("updated_by", :integer, :null => false)
          t.column("updated_at", :datetime)
        end

        foreign_key(:user_contacts, :user_id, :users)
        foreign_key(:user_contacts, :user_contact_type_id, :user_contact_types)
        foreign_key(:user_contacts, :updated_by, :updaters)
      end

      def drop_user_contacts_table
        drop_table_with_history(:user_contacts)
      end

      def create_system_objects_table
        create_table_with_privies(:system_objects, :force => true) do |t|
          t.column("name", :text)
          t.column("can_remove", :boolean, :default => true)
        end

        create_lookup_table(:roles,:system_objects)
        create_lookup_table(:system_objects,:user_groups)
      end

      def drop_system_objects_table
        drop_lookup_table(:system_objects,:user_groups)
        drop_lookup_table(:roles,:system_objects)
        drop_table(:system_objects)
      end


      def create_system_methods_table
        create_table_with_privies(:system_methods, :force => true) do |t|
          t.column("name", :text)
          t.column("system_object_id", :integer, :null => false)
        end

        foreign_key(:system_methods, :system_object_id, :system_objects)
      end

      def drop_system_methods_table
        drop_table(:system_methods)
      end
  end #class block
end
